package com.cskaoyan.order.mq.delay;

import com.cskaoyan.mall.commons.exception.BizException;
import com.cskaoyan.mall.order.constant.OrderRetCode;
import com.cskaoyan.order.biz.constant.OrderConstants;
import com.cskaoyan.order.dal.entitys.Order;
import com.cskaoyan.order.dal.persistence.OrderMapper;
import com.cskaoyan.order.dto.CancelOrderRequest;
import com.cskaoyan.order.service.OrderCoreService;
import com.cskaoyan.order.service.impl.OrderCoreServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;

/**
 * @auther cskaoyan
 * @date 2022/7/12:17:43
 */
@Component
@Slf4j
public class DelayOrderCancelConsumer {


    private DefaultMQPushConsumer consumer;

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    OrderCoreService orderCoreService;

    @PostConstruct
    public void init() {
        consumer = new DefaultMQPushConsumer("delay_order_cancel_consumer");

        consumer.setNamesrvAddr("127.0.0.1:9876");

        try {
            consumer.subscribe("delay_order_cancel", "*");

            consumer.setMessageListener(new MessageListenerConcurrently() {

                @Override
                @Transactional
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                    // 订单超时自动取消的逻辑
                    // 1. 获取延迟消息，从消息体中，获取orderId
                    try {
                        String orderId = new String(msgs.get(0).getBody());
                        // 2. 检查orderId对应的订单状态，如果订单的状态是已支付，或者已取消
                        Order order = orderMapper.selectByPrimaryKey(orderId);
                        if(ObjectUtils.isEmpty(order)){
                            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                        }
                        if (OrderConstants.ORDER_STATUS_PAYED == order.getStatus() ||
                                OrderConstants.ORDER_STATUS_TRANSACTION_CANCEL == order.getStatus()) {
                            log.info("订单已支付，编号"+orderId);
                            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                        }
                        // 3. 如果订单的状态还是初始化状态，取消该订单
                        //    a. 修改订单状态，修改为已取消
                        //    b. 根据orderId，去tb_order_item查询订单对应的，所有订单商品条目，
                        //       根据每个商品下单的数量 -lock_count +stockCount
                        Order updateOrder = new Order();
                        updateOrder.setOrderId(orderId);
                        updateOrder.setUpdateTime(new Date());
                        updateOrder.setStatus(OrderConstants.ORDER_STATUS_TRANSACTION_CANCEL);
                        int affectedRows = orderMapper.updateByPrimaryKeySelective(updateOrder);
                        if(affectedRows<1){
                            throw new BizException(OrderRetCode.DB_EXCEPTION.getCode(), "取消订单更新状态码失败");
                        }
                        orderCoreService.updateStockAndOrderItemWhenCancel(orderId);
                        return  ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                    } catch (Exception e) {
                        log.error("处理订单超时取消发生异常"+e);
                        return  ConsumeConcurrentlyStatus.RECONSUME_LATER;
                    }
                }
            });

            // 启动consumer
            consumer.start();
        } catch (MQClientException e) {
            log.error("订单延时消息处理出现异常" + e);
        }
    }


}
